From aa0ec774bf7d4b63641b1cdc887103cb7da65f55 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 24 Dec 2016 06:16:54 +0100 Subject: [PATCH] vulkan: Add proof-of-concept clip implementation We can now clip to cicular rounded rectangles when drawing colors. --- gsk/gskvulkanrender.c | 3 +- gsk/gskvulkanrenderpass.c | 9 +++- gsk/gskvulkanrenderprivate.h | 1 + .../vulkan/color-clip-rounded.frag.glsl | 51 ++++++++++++++++++ .../vulkan/color-clip-rounded.frag.spv | Bin 0 -> 5228 bytes .../vulkan/color-clip-rounded.vert.glsl | 36 +++++++++++++ .../vulkan/color-clip-rounded.vert.spv | Bin 0 -> 2176 bytes 7 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 gsk/resources/vulkan/color-clip-rounded.frag.glsl create mode 100644 gsk/resources/vulkan/color-clip-rounded.frag.spv create mode 100644 gsk/resources/vulkan/color-clip-rounded.vert.glsl create mode 100644 gsk/resources/vulkan/color-clip-rounded.vert.spv diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index e2e8167b4c..d23ff8cd3e 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -314,7 +314,8 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self, GskVulkanPipeline * (* create_func) (GskVulkanPipelineLayout *layout, const char *name, VkRenderPass render_pass); } pipeline_info[GSK_VULKAN_N_PIPELINES] = { { "blit", gsk_vulkan_blend_pipeline_new }, - { "color", gsk_vulkan_color_pipeline_new } + { "color", gsk_vulkan_color_pipeline_new }, + { "color-clip-rounded", gsk_vulkan_color_pipeline_new } }; g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL); diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index dc26f31f1c..21a5cb9c88 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -98,6 +98,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, .type = GSK_VULKAN_OP_FALLBACK, .render.node = node }; + GskVulkanPipelineType pipeline_type; switch (gsk_render_node_get_node_type (node)) { @@ -126,10 +127,14 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, return; case GSK_COLOR_NODE: - if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + pipeline_type = GSK_VULKAN_PIPELINE_COLOR; + else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) + pipeline_type = GSK_VULKAN_PIPELINE_COLOR_CLIP_ROUNDED; + else FALLBACK ("Color nodes can't deal with clip type %u\n", constants->clip.type); op.type = GSK_VULKAN_OP_COLOR; - op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_COLOR); + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type); g_array_append_val (self->render_ops, op); return; diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h index e44f2639f2..c5f7379daf 100644 --- a/gsk/gskvulkanrenderprivate.h +++ b/gsk/gskvulkanrenderprivate.h @@ -12,6 +12,7 @@ G_BEGIN_DECLS typedef enum { GSK_VULKAN_PIPELINE_BLIT, GSK_VULKAN_PIPELINE_COLOR, + GSK_VULKAN_PIPELINE_COLOR_CLIP_ROUNDED, /* add more */ GSK_VULKAN_N_PIPELINES } GskVulkanPipelineType; diff --git a/gsk/resources/vulkan/color-clip-rounded.frag.glsl b/gsk/resources/vulkan/color-clip-rounded.frag.glsl new file mode 100644 index 0000000000..9825f7858d --- /dev/null +++ b/gsk/resources/vulkan/color-clip-rounded.frag.glsl @@ -0,0 +1,51 @@ +#version 420 core + +layout(location = 0) in vec2 inPos; +layout(location = 1) in vec4 inColor; +layout(location = 2) in vec4 inClipBounds; +layout(location = 3) in vec4 inClipWidths; + +layout(location = 0) out vec4 color; + +struct RoundedRect { + vec4 bounds; + vec4 corners; +}; + +float clip(vec2 pos, RoundedRect r) { + vec2 ref_tl = r.bounds.xy + vec2( r.corners.x, r.corners.x); + vec2 ref_tr = r.bounds.zy + vec2(-r.corners.y, r.corners.y); + vec2 ref_br = r.bounds.zw + vec2(-r.corners.z, -r.corners.z); + vec2 ref_bl = r.bounds.xw + vec2( r.corners.w, -r.corners.w); + + float d_tl = distance(pos, ref_tl); + float d_tr = distance(pos, ref_tr); + float d_br = distance(pos, ref_br); + float d_bl = distance(pos, ref_bl); + + float pixels_per_fragment = length(fwidth(pos.xy)); + float nudge = 0.5 * pixels_per_fragment; + vec4 distances = vec4(d_tl, d_tr, d_br, d_bl) - r.corners + nudge; + + bvec4 is_out = bvec4(pos.x < ref_tl.x && pos.y < ref_tl.y, + pos.x > ref_tr.x && pos.y < ref_tr.y, + pos.x > ref_br.x && pos.y > ref_br.y, + pos.x < ref_bl.x && pos.y > ref_bl.y); + + float distance_from_border = dot(vec4(is_out), + max(vec4(0.0, 0.0, 0.0, 0.0), distances)); + + // Move the distance back into pixels. + distance_from_border /= pixels_per_fragment; + // Apply a more gradual fade out to transparent. + //distance_from_border -= 0.5; + + return 1.0 - smoothstep(0.0, 1.0, distance_from_border); +} + +void main() +{ + RoundedRect r = RoundedRect(vec4(inClipBounds.xy, inClipBounds.xy + inClipBounds.zw), inClipWidths); + + color = vec4(inColor.rgb * inColor.a, inColor.a) * clip (inPos, r); +} diff --git a/gsk/resources/vulkan/color-clip-rounded.frag.spv b/gsk/resources/vulkan/color-clip-rounded.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..cf650af95c1e4dfd8adf4a9f3e785c175552c639 GIT binary patch literal 5228 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 M{mU%1{eOc00BXeNeE=MRtHmmYEGZi+HCOK7jAw zLwaN4|Mhgk^ron;zy7YOuC5{1KG9)Jn|__9V$#)b+GQKlV~SQ+wm)vqHj~=y{K6cJ zUX!y#IDO`_-RJf9crT1FMkKc-4q3yk9gg2B^%G&flZY8P_yI|i!b~&!cC!WLGgi#7nH}3>T)?s|!14d*!*S&X>l`*;)6#vhz{L zfHK1wR~^{whqNn7mn6f=!#%O_4a)A6E=gEZ&hFA4&Zz8eY0iL^WYcSW;LFbDdjR7+ zI{k8unO1)}ORZpt=k#fB%#StCq4!{LJl5}QaF1Qp9y`UlY#jr#$w3UxAnf5%^EGMe zKH3(G<%OV=O^E~_S8o{AFr%^mj6aJbGfLwL33vooWDZ& zjycPF@;{eaSLJ2?n1L1fh<{ze`|XGU=Z3?;S=8*gH?_}lM`eQ{)Ie^yeg=5w*Q#V( z`i_L$B?%mIO-R6hx!J#~Ju$(5I_#eI)P#@vxeFL^d8fw`-i|pSE^js`0rz>HXwSL# zI>W3zm4LB4_Dp*)?z^k%=*_$YErHeGvfIh4u{VyrFP2Slub{V5zl|CJvjWbH1